#ifndef STRINGHELPER_H
#define STRINGHELPER_H

#include <algorithm>
#include <cctype>
#include <string>
#include <sstream>
#include <Windows.h>

#if UNICODE
#define ToLower ToLowerW
#else
#define ToLower ToLowerA
#endif

class StringHelper
{
public:
	static void ToLowerA(std::string &str)
	{
		ToLowerA(str,str.begin());
	}

	static void ToLowerA(std::string &str,std::string::iterator dest)
	{
		transform(str.begin(),str.end(),dest,tolower);
	}

	static void ToUpperA(std::string &str)
	{
		ToUpperA(str,str.begin());
	}

	static void ToUpperA(std::string &str,std::string::iterator dest)
	{
		transform(str.begin(),str.end(),dest,toupper);
	}

	static bool StartWithA(const std::string &str1,const std::string &str2)
	{
		if(str1.size()<str2.size())
		{
			return false;
		}
		else
		{
			return equal(str2.begin(),str2.end(),str1.begin());
		}
	}

	static bool EndWithA(const std::string &str1,const std::string &str2)
	{
		if(str1.size()<str2.size())
		{
			return false;
		}
		else
		{
			return equal(str2.rbegin(),str2.rend(),str1.rbegin());
		}
	}

	static void ToLowerW(std::wstring &str)
	{
		ToLowerW(str,str.begin());
	}

	static void ToLowerW(std::wstring &str,std::wstring::iterator dest)
	{
		transform(str.begin(),str.end(),dest,tolower);
	}

	static void ToUpperW(std::wstring &str)
	{
		ToUpperW(str,str.begin());
	}

	static void ToUpperW(std::wstring &str,std::wstring::iterator dest)
	{
		transform(str.begin(),str.end(),dest,toupper);
	}

	static bool StartWithW(const std::wstring &str1,const std::wstring &str2)
	{
		if(str1.size()<str2.size())
		{
			return false;
		}
		else
		{
			return equal(str2.begin(),str2.end(),str1.begin());
		}
	}

	static bool EndWithW(const std::wstring &str1,const std::wstring &str2)
	{
		if(str1.size()<str2.size())
		{
			return false;
		}
		else
		{
			return equal(str2.rbegin(),str2.rend(),str1.rbegin());
		}
	}

	static std::string::size_type ReadToSpaceA(const std::string &src,std::string::size_type startIndex,std::string &dest)
	{
		std::string::size_type ret = src.find_first_of(' ',startIndex);
		if(ret!=std::string::npos)
		{
			dest.append(src.begin()+startIndex,src.begin()+ret);
		}
		else
		{
			dest.append(src.begin()+startIndex,src.end());
		}
		return ret;
	}

	static std::string::size_type ReverseReadToSpaceA(const std::string &src,std::string::size_type startIndex,std::string &dest)
	{
		std::string::size_type ret = src.find_last_of(' ',startIndex);
		if(ret!=std::string::npos)
		{
			dest.append(src.begin()+ret+1,src.end());
		}
		else
		{
			dest.append(src.begin(),src.end());
		}
		return ret;
	}

	template<typename T> static std::string ToString(T numericValue)
	{
		std::ostringstream os;
		os<<numericValue;
		return os.str();
	}

	static std::wstring* MultiByteToUnicode(const std::string &str)
	{
		LPWSTR buffer=NULL;
		std::wstring *result=NULL;
		try
		{
			UINT codePage=::GetACP();
			int size=::MultiByteToWideChar(codePage,0,str.c_str(),-1,NULL,0);
			if(size==0)
			{
				return NULL;
			}
			buffer=reinterpret_cast<LPWSTR>(new BYTE[size*sizeof(wchar_t)]);
			size=::MultiByteToWideChar(codePage,0,str.c_str(),-1,buffer,size);
			if(size==0)
			{
				delete []buffer;
				return NULL;
			}
			result=new std::wstring(buffer);
			delete []buffer;
			return result;
		}
		catch(...)
		{
			delete []buffer;
			delete result;
			return NULL;
		}
	}

	static char* UnicodeToMultiByte(const wchar_t *str)
	{
		LPSTR buffer=NULL;
		try
		{
			UINT codePage=::GetACP();
			int size=::WideCharToMultiByte(codePage,0,str,-1,NULL,0,NULL,NULL);
			if(size==0)
			{
				return NULL;
			}
			buffer=reinterpret_cast<LPSTR>(new BYTE[size]);
			size=::WideCharToMultiByte(codePage,0,str,-1,buffer,size,NULL,NULL);
			if(size==0)
			{
				delete []buffer;
				return NULL;
			}
			return buffer;
		}
		catch(...)
		{
			delete []buffer;
			return NULL;
		}
	}
};

#endif